﻿using System;
using System.Collections.Generic;

namespace CxExtension
{
	public class ObjectPoolManager<K,T> where T : class, new()
	{
		protected Dictionary<K, ObjectPool<T>> mPoolMap = new Dictionary<K, ObjectPool<T>>();

		public T Get(K k)
		{
			var pool = mPoolMap.GetOrNewAdd(k);
			return pool.Get();
		}

		public void Recycle(K k,T value)
		{
			var pool = mPoolMap.GetOrNewAdd(k);
			pool.Recycle(value);
		}
	}

	/// <summary>
	/// 一个简单的对象池,提供了重置时的回调
	/// a sample pool  and your self ensure multile tiems return.used to single thread
	/// </summary>
	/// <typeparam name="T"></typeparam>
	public class ObjectPool<T> : IPool<T> where T :new()
	{
		protected Queue<T> bGetQue = new Queue<T>();
		protected Queue<T> bReturnQue;
		protected Func<T> bCreateNew;
		protected Action<T> mResetAction;
		protected string mName;

		public ObjectPool(Func<T> createNew, Action<T> resetFunc) : this()
		{
			bCreateNew = createNew;
			mResetAction = resetFunc;
		}
		public ObjectPool()
		{
			bReturnQue = bGetQue;
		}
		public T Get()
		{
			T it = default(T);
			if (HasFreeItem)
			{
				it = bGetQue.Dequeue();
			}
			else
			{
				it = bCreateNew == null ? new T() : bCreateNew();
			}
			return it;
		}

		public void Recycle(T value)
		{
			if (mResetAction != null) mResetAction(value);

			bGetQue.Enqueue(value);
		}

		public bool HasFreeItem => bGetQue.Count > 0;

		/// <summary>
		/// 设置创建函数
		/// </summary>
		/// <param name="v"></param>
		public void SetCreateNew(Func<T> v)
		{
			bCreateNew = v;
		}

		public void SetResetAction(Action<T> v)
		{
			mResetAction = v;
		}

	}

	/// <summary>
	/// 异步的对象池
	/// </summary>
	/// <typeparam name="T"></typeparam>
	public class ObjectPoolAsync<T> : IPool<T> where T : class, new()
	{
		private readonly ObjectPool<T> mPool = new ObjectPool<T>();                      //
		private readonly object mLocker = new object();
		public T Get()
		{
			lock (mLocker)
			{
				return mPool.Get();
			}
		}

		public void Recycle(T item)
		{
			lock (mLocker)
			{
				mPool.Recycle(item);
			}
		}

		public ObjectPool<T> Pool { get { return mPool; } }
	}
	/// <summary>
	/// 实现了重置接口的对象池
	/// </summary>
	/// <typeparam name="T"></typeparam>
	public class ObjectPoolR<T> : IPool<T> where T : class, IReset, new()
	{
		private ObjectPool<T> mPool;                      //

		public ObjectPoolR()
		{
			mPool = new ObjectPool<T>();
		}

		public ObjectPoolR(ObjectPool<T> pool)
		{
			mPool = pool;
		}

		public T Get()
		{
			return mPool.Get();
		}

		public void Recycle(T item)
		{
			if (item == null) return;
			item.Reset();
			mPool.Recycle(item);
		}
	}
}
